[源码]Elasticsearch源码6(5.4插件开发)

本文重点讨论基于5.4.3版本的ES在gradle构建项目的环境下如何做插件开发。

一、前言

1.1 5.4 和 2.x 源码开发的差别

  • 构建方式从maven变成了gradle这个是最大的差别,而对于ES核心包的插件模块来说只是做了优化,对于开发者来说掌握了2.x的开发就可以迅速上手5.4.x的开发。

1.2 插件调试与DEBUG

  • 没有办法直接把编译后的发行版目录位置做软链挂载到配置文件了,只能自己编译后解压到{ES_HOME}/plugins文件夹下了。

原因如下

  • 2.X版本的ES插件加载目录获取
1
2
3
4
5
6
7
8
9
10
public class Environment{
public Environment(Settings settings) {
//...其他略
if (settings.get("path.plugins") != null) {
pluginsFile = PathUtils.get(cleanPath(settings.get("path.plugins")));//code1
} else {
pluginsFile = homeFile.resolve("plugins");
}
}
}
  • 5.4.3版本的ES插件加载目录获取
1
2
3
4
5
6
public class Environment{
public Environment(Settings settings) {
//...其他略
pluginsFile = homeFile.resolve("plugins");
}
}
  • code1 生生被干掉了。。。so 只能老老实实 assembly then copy了。

二、5.4.3插件开发

2.1 启动项目

第一步当然是要把5.4.3的源码项目启动起来。下面我们逐步操作。

1) 下载项目

1
$ git clone https://github.com/elastic/elasticsearch.git

2) 项目根目录执行gradle idea,使项目按照idea的方式构建

3) idea打开项目并且import gradle project导入项目。

4) 创建${ES_HOME}/config,把distribution/src/main/resources/config 的文件都 copy 过来(不用拷jvm.options)

  • 我们的${ES_HOME}就是$USER_HOME/elasticsearch-v5.4.3/core

  • jvm.options 是通过启动脚本生效的,我们不用纠结这个文件。

5) 启动发生access denied异常

1
2
3
4
2017-03-08 11:06:11,447 main ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTrustPermission" "register")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:585)
...
  • 解决方案:添加 -Djava.security.policy=/home/wangdi/IdeaWorkspace/sourcecode/elasticsearch-v5.4.3/core/config/elasticsearch.policy

内容如下

1
2
3
4
grant {
permission javax.management.MBeanTrustPermission "register";
permission javax.management.MBeanServerPermission "createMBeanServer";
};

6) 如果报Exception: java.security.AccessControlException thrown from the UncaughtExceptionHandler in thread之类的其他权限异常。

  • 解决方案:直接把elasticsearch.policy改为。(暴力点)
1
2
3
grant {
permission java.security.AllPermission;
};

7) 创建${ES_HOME}/plugins文件夹

和2.x开发是一样的,先空着。

8) Unsupported transport.type异常

1
2
3
4
...
[2017-09-14T11:10:01,550][WARN ][o.e.b.ElasticsearchUncaughtExceptionHandler] [] uncaught exception in thread [main]
org.elasticsearch.bootstrap.StartupException: java.lang.IllegalStateException: Unsupported transport.type []
...
  • 解决方法:
    • 根目录modules模块下找到transport-netty3或者transport-netty4模块,构建netty子模块。
    • 然后modules/transport-netty3/build/distributions下面找到发行版的zip包。
    • 最后再核心包下的modules目录下建个文件夹叫transport-netty3transport-netty4(模块名),把对应的zip包解压到这里。

9) jvm参数校验异常

1
2
3
4
...
ERROR: [1] bootstrap checks failed
[1]: initial heap size [130023424] not equal to maximum heap size [2071986176]; this can cause resize pauses and prevents mlockall from locking the entire heap
...
  • 解决方法: 添加启动参数 -Xms1g -Xmx1g

再提一下 jvm.options 是通过启动脚本生效的,我们不用纠结这个文件。自己在idea配置jvm启动参数,启动参数如下。

1
-Xms1g -Xmx1g -ea -Delasticsearch -Des.foreground=yes -Des.path.home=/home/wangdi/IdeaWorkspace/sourcecode/elasticsearch-v5.4.3/core -Djava.security.policy=/home/wangdi/IdeaWorkspace/sourcecode/elasticsearch-v5.4.3/core/config/elasticsearch.policy

elasticsearch.yml如下。详情参见:elasticsearch.yml的配置属性官方解释

1
2
3
4
5
6
7
path.logs: /usr/share/elasticsearch5/logs
path.data: /usr/share/elasticsearch5/data

http.cors.enabled: true
http.cors.allow-origin: "*"

network.host: 0.0.0.0

10) 项目启动成功,开始开发调试

2.2 插件开发项目结构

核心包模块结构如下

图 es5plugin-core

插件模块结构如下

图 es5plugin-plugin

2.3 5.4.3插件开发源码分析

我们简单看下ActionLoggingPlugin这个 ES 源码测试用例中提供的插件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public static class ActionLoggingPlugin extends Plugin implements ActionPlugin {

@Override
public Collection<Module> createGuiceModules() {
return Collections.<Module>singletonList(new ActionLoggingModule());
}

@Override
public List<Class<? extends ActionFilter>> getActionFilters() {
return singletonList(LoggingFilter.class);
}
}

public static class ActionLoggingModule extends AbstractModule {
@Override
protected void configure() {
bind(LoggingFilter.class).asEagerSingleton();
}

}

public static class LoggingFilter extends ActionFilter.Simple {

private final ThreadPool threadPool;

@Inject
public LoggingFilter(Settings settings, ThreadPool pool) {
super(settings);
this.threadPool = pool;
}

@Override
public int order() {
return 999;
}

@Override
protected boolean apply(String action, ActionRequest request, ActionListener<?> listener) {
requests.add(new RequestAndHeaders(threadPool.getThreadContext().getHeaders(), request));
return true;
}
}

结论就是,ES的 >>5.4.x 版本对插件做了优化重构,但是对于开发者来说和2.x插件开发几乎无异。